package com.lyy.mybatis.sensitive.demo.dbhandler;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * db中 {"k1":"v1" ....}          可解析为 DTO等对象
 *
 * @param <T>
 */
@MappedTypes(List.class)
@MappedJdbcTypes({JdbcType.VARCHAR})
@Slf4j
public abstract class JacksonObjTypeHandler<T> extends BaseTypeHandler<T> {
    /**
     * 具体类型，由子类提供
     *
     * @return 具体类型
     */
    protected abstract TypeReference<T> specificType();

    /**
     * 例如：
     * import com.sgd.common.dbhandler.JsonTypeHandler;
     * import org.apache.ibatis.type.TypeReference;
     * <p>
     * public class FileInfoJsonTypeHandler extends JsonTypeHandler<XxDTO> {
     *
     * @Override protected TypeReference<XxDTO> specificType() {
     * return new TypeReference<XxDTO>() {
     * };
     * }
     * }
     */

    @SneakyThrows
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType){
        String content = ObjectUtil.isEmpty(parameter) ? null :  JacksonObjectMapper.instance.writeValueAsString(parameter);
        ps.setString(i, content);
    }

    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return this.getListByJsonArrayString(rs.getString(columnName));
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return this.getListByJsonArrayString(rs.getString(columnIndex));
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return this.getListByJsonArrayString(cs.getString(columnIndex));
    }

    public T getListByJsonArrayString(String content) {
        try {
            return StrUtil.isBlank(content) ? null : JacksonObjectMapper.instance.readValue(content, this.specificType());
        } catch (JsonProcessingException e) {
            log.warn("json解析失败:{}", e.getMessage());
            return null;
        }
    }
}
